package com.voxel.sense.infomsg.module.home;

import android.location.Location;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.util.Log;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.LatLngBounds;
import com.amap.api.services.core.AMapException;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.geocoder.GeocodeAddress;
import com.amap.api.services.geocoder.GeocodeQuery;
import com.amap.api.services.geocoder.GeocodeResult;
import com.amap.api.services.geocoder.GeocodeSearch;
import com.amap.api.services.geocoder.RegeocodeQuery;
import com.amap.api.services.geocoder.RegeocodeResult;
import com.example.com.common.app.BasePresenter;
import com.example.com.common.factory.data.DataSource;
import com.example.com.common.utils.L;
import com.example.com.common.utils.NetworkUtils;
import com.example.com.common.utils.TimeUtils;
import com.example.com.common.utils.ToastUtil;
import com.example.com.common.utils.constants.TimeConstants;
import com.google.gson.Gson;
import com.voxel.sense.infomsg.R;
import com.voxel.sense.infomsg.utils.GPSUtils;
import com.voxel.sense.infomsg.utils.ResourceUtil;

import java.util.ArrayList;
import java.util.List;

import cyy.example.com.facotry.Factory;
import cyy.example.com.facotry.model.api.BaseEntity;
import cyy.example.com.facotry.model.api.response.BannerEntity;
import cyy.example.com.facotry.model.api.response.FirmLocationEntity;
import cyy.example.com.facotry.model.api.response.WarnCountEntity;
import cyy.example.com.facotry.net.RequestIdFactory;
import cyy.example.com.facotry.net.helper.FirmNetHelper;
import cyy.example.com.facotry.net.helper.NetHelper;
import cyy.example.com.facotry.share.SPEngine;

/**
 * Created by ChenYiYao on 2018/2/5.
 */

public class HomePresenter extends BasePresenter<HomeContract.View>
        implements HomeContract.Presenter, DataSource.Callback<BaseEntity>,
        AMap.OnMyLocationChangeListener, GeocodeSearch.OnGeocodeSearchListener, AMapLocationListener {

    private GeocodeSearch mGeocodeSearch; //地图编码查询
    private List<FirmLocationEntity> mFirmsDataList;

    private long mLastRefreshLocationTime = 0;//上次位置更新时间

    //标识，用于判断是否只显示一次定位信息和用户重新定位
    private boolean isFirstLoc = true;
    private boolean mLoadFail = false;//网络加载失败
    private boolean mIsUpLocation = true; //标记是否上传位置
    private String mOldCity;

    //定位工具
    AMapLocationClient mLocationClient = null;

    public HomePresenter(HomeContract.View view) {
        super(view);
    }

    @Override
    public void start() {
        super.start();
        //地图自身的定位按钮定位的回调
        if (mGeocodeSearch == null) {
            try {
                mGeocodeSearch = new GeocodeSearch(Factory.app());
            } catch (AMapException e) {
                e.printStackTrace();
            }
            mGeocodeSearch.setOnGeocodeSearchListener(this);
        }
    }

    @Override
    public void destroy() {
        super.destroy();
        //销毁时，需要销毁定位client
        if (null != mLocationClient) {
            mLocationClient.onDestroy();
        }
    }

    @Override
    public void SearchCityLocation(String city, String oldCity) {
        mView.RefreshPointCity("定位中");
        mOldCity = oldCity;
        GeocodeQuery geocodeQuery = new GeocodeQuery(city, "");
        mGeocodeSearch.getFromLocationNameAsyn(geocodeQuery);
    }

    @Override
    public List<FirmLocationEntity> getFirmDataList() {
        return mFirmsDataList;
    }

    @Override
    public AMap.OnMyLocationChangeListener getMyLocationChangeListener() {
        return this;
    }

    @Override
    public GeocodeSearch.OnGeocodeSearchListener getGeocodeSearchListener() {
        return this;
    }

    @Override
    public void loadBannerData() {
        //轮播图数据，三天更新一次
        long banneLoadTime = SPEngine.getSPEngine().getBanneLoadTime();
        TimeUtils.getMillis(banneLoadTime, 3, TimeConstants.DAY);
        String bannerList = SPEngine.getSPEngine().getBannerList();
        NetHelper.getBannerList(this);
//        if (banneLoadTime == 0 || TextUtils.isEmpty(bannerList) || (System.currentTimeMillis() - TimeConstants.DAY * 3) > banneLoadTime) {
//        } else {
//            //上次更新时间没有超过3天，从sp中加载
//            Gson gson = new Gson();
//            Type type = new TypeToken<List<BannerEntity>>() {
//            }.getType();
//            List<BannerEntity> entityList = gson.fromJson(bannerList, type);
//            if (entityList != null && entityList.size() > 0) {
//                mView.setBannerDatas(entityList);
//            } else {
//                NetHelper.getBannerList(this);+
//
//            }
//        }
        //加载轮播图数据
    }

    @Override
    public void changeUpCondition(boolean b) {
        mIsUpLocation = b;
    }

    @Override
    public void doClockIn() {
        if (!NetworkUtils.isConnected()) {
            ToastUtil.showToastLong(Factory.app(), ResourceUtil.getString(Factory.app(), "network_unavailable"));
            return;
        }

        if (mLocationClient == null) {
            try {
                mLocationClient = new AMapLocationClient(((Fragment) mView).getContext());
            } catch (Exception e) {
                e.printStackTrace();
            }
            AMapLocationClientOption option = new AMapLocationClientOption();
            option.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
            option.setOnceLocation(true);
            option.setOnceLocationLatest(true);
            option.setMockEnable(false);
            option.setWifiScan(true);
            option.setGpsFirst(false);
            option.setLocationPurpose(AMapLocationClientOption.AMapLocationPurpose.SignIn);
            mLocationClient.setLocationOption(option);
            //设置定位监听
            mLocationClient.setLocationListener(this);
        }
//        mView.showLoading("");
        mLocationClient.startLocation();
    }

    @Override
    public void getWarnCount() {
        NetHelper.getWarnCount(this);
    }

    @Override
    public void getWifiWarnCount() {
        Log.e("+++++", "我操");
        NetHelper.getWifiWarnCount(this);
    }

    @Override
    public void LoadMarkerInfo() {
        //获取企业位置信息
        FirmNetHelper.getAllFirmLocation(this);
    }

    @Override
    public void onDataLoaded(BaseEntity entity, int reqId) {
        if (mView == null) {
            return;
        }
        if (RequestIdFactory.UP_MY_LOCATION == reqId) {//上传位置
            //定位回调
            if (entity.isSuccess()) {
                //位置上传成功
                //位置上传成功
            }
        } else if (reqId == RequestIdFactory.CLOCK_IN) {//打卡
            mView.dimissLoading();
            if (entity.isSuccess()) {
                Factory.app().getResources().getString(R.string.clock_in_success);
                mView.onClickInSuccess();
                ToastUtil.showToastLong(Factory.app(), "打卡成功！");
            } else {
                mView.showError(Factory.app().getResources().getString(R.string.clock_in_failed));
            }
        } else if (RequestIdFactory.FIRM_LOCATION == reqId) { //所有公司位置
            if (entity.isSuccess()) {
                mFirmsDataList = (List<FirmLocationEntity>) entity.getData();
                makeMarkerData(mFirmsDataList);
            } else {
                mLoadFail = false;
            }
        } else if (RequestIdFactory.GET_BANNER_DATAS == reqId) {//轮播图
            List<BannerEntity> bannerList = (List<BannerEntity>) entity.getData();
            if (bannerList != null && bannerList.size() > 0) {
                //存入sp中
                Gson gson = new Gson();
                String json = gson.toJson(bannerList);
                SPEngine.getSPEngine().setBannerList(json);
                SPEngine.getSPEngine().setBanneLoadTime(System.currentTimeMillis());
                mView.setBannerDatas(bannerList);
            } else {
                //木有轮播图，加载一张默认图片
                loadDefBanner();

            }
        }else if(RequestIdFactory.WARN_COUNT == reqId){
            //警告条数
            WarnCountEntity count = (WarnCountEntity) entity.getData();
            mView.setWarinCount(count.getCount());
        }else if(RequestIdFactory.Wifi_WARN_COUNT_ONE == reqId){
            String count = (String) entity.getData();
            mView.setWifiWarnCount(count);
        }
    }

    private void loadDefBanner() {
        ArrayList list1 = new ArrayList();
        list1.add(R.mipmap.banner);
        mView.setBannerDatas(list1);
    }

    private void makeMarkerData(List<FirmLocationEntity> beanList) {
        if (mView == null && beanList != null && beanList.size() > 0) {
            return;
        }
        AMap map = mView.getMap();
        if (map != null && beanList != null && beanList.size() > 0) {
            LatLngBounds.Builder builder = new LatLngBounds.Builder();
            L.d("------------------------公司数量：" + beanList.size());
            //由于服务器坐标都是百度坐标，这里需要转换坐标系
            for (FirmLocationEntity bean : beanList) {
                String latitudeStr = bean.getLatitude();
                String longitudeStr = bean.getLongitude();
                if (!TextUtils.isEmpty(latitudeStr) && !TextUtils.isEmpty(longitudeStr)) {
                    try {
                        double latitude = Double.parseDouble(bean.getLatitude());
                        double longitude = Double.parseDouble(bean.getLongitude());
                        double[] doubles = GPSUtils.bd09_To_Gcj02(latitude, longitude);
                        bean.setLatitude(doubles[0] + "");
                        bean.setLongitude(doubles[1] + "");
                        //收集所有企业的范围
                        builder.include(new LatLng(doubles[0], doubles[1]));

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
//            mView.getMap().addMarkers(markerOptionlst, true);
            int width = Factory.app().getResources().getDrawable(R.mipmap.a_level_firm).getIntrinsicWidth();
            int height = Factory.app().getResources().getDrawable(R.mipmap.a_level_firm).getIntrinsicHeight();
            //设置地图显示的区域范围
//            mView.getMap().moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), Math.max(width, height)));

            mView.onShowtMarker(beanList);
        }
    }

    @Override
    public void onDataNotAvailable(String strRes, int reqId) {
        if (mView == null) {
            return;
        }

        if (RequestIdFactory.UP_MY_LOCATION == reqId) {
            //上传定位回调
            //由于会不断的更新位置，若是网络不开启等状态，会一直失败，若有提示等操作处理，也会影响用户体验。暂不做处理
        } else if (reqId == RequestIdFactory.CLOCK_IN) {//打卡
//            mView.showError(strRes);
            mView.showError(strRes);
            mView.dimissLoading();
        } else if (RequestIdFactory.GET_BANNER_DATAS == reqId) {//轮播图
            //加载三张默认图片
            mView.showError(strRes);
            loadDefBanner();
            mView.showError(strRes);
        } else if (RequestIdFactory.FIRM_LOCATION == reqId) {//获取所有公司
            mLoadFail = true;
        }
    }

    /**
     * 定位回调方法
     *
     * @param location location
     */
    @Override
    public void onMyLocationChange(Location location) {
        if (mView == null)
            return;
        if (location != null &&
                !(location.getLatitude() == 0 && location.getLongitude() == 0)) {
            //TODO 该方式是直接截取了字符，存在一定的问题。
            String s = location.toString();
            int start = s.indexOf("#city");//记录城市的开始位置
            int end = s.indexOf("#district");//记录城市的开始位置
            String city = s.substring(start + 6, end);

            double latitude = location.getLatitude();
            double longitude = location.getLongitude();
            SPEngine.getSPEngine().getUserInfo().setlatitude(latitude + "");
            SPEngine.getSPEngine().getUserInfo().setLonggiude(longitude + "");

            //在定位回调中更新我的位置，先判断刷新的间隔时间，是否大于位置更新时间，是的话刷新我在服务器的位置
            long myLocationRefreshTime = SPEngine.getSPEngine().getMyLocationRefreshTime();
            if (mIsUpLocation && ((System.currentTimeMillis() - mLastRefreshLocationTime) >= myLocationRefreshTime)) {
                //将坐标转为百度坐标上传服务器
                double[] doubles = GPSUtils.gcj02_To_Bd09(latitude, longitude);
                mLastRefreshLocationTime = System.currentTimeMillis();
                clickCard(doubles[0], doubles[1]);
                NetHelper.UpMyLocation(doubles[0], doubles[1], this);
            }

            //公司数据无法获取到，重新加载
            if (mFirmsDataList == null && mLoadFail) {
                FirmNetHelper.getAllFirmLocation(this);
            }


            if (isFirstLoc) {
                //第一次定位，获取位置
                //使地区显示指定的区域
                isFirstLoc = false;
//                aMap.moveCamera(CameraUpdateFactory.zoomTo(9));
                L.d("onMyLocationChange-移动中心点");
                mView.RefreshPointCity(city);
//                mView.RefreshMapCamera(latLonPoint.getLatitude(), latLonPoint.getLongitude());
                //boolean值 -表示是否需要检查经纬度的合法性，建议填写true 如果设为true，
                // 传入的经纬度不合理，会打印错误日志进行提示，然后转换为接近的合理的经纬度 ;
//                getAddress(latLonPoint);
                //定位成功，将位置一并上传到高德云服务
            }
        } else {
            if (NetworkUtils.isConnected() && isFirstLoc) {
                //避免频繁弹出toast，影响用户体验，只有未定位成功过才弹出提示
                ToastUtil.showToastLong(Factory.app(), "定位失败");
            }
        }
    }

    private void clickCard(double latitude, double longgiude) {
        NetHelper.UserClockIn(latitude, longgiude, new DataSource.Callback<BaseEntity>() {
            @Override
            public void onDataNotAvailable(String strRes, int reqId) {
            }

            @Override
            public void onDataLoaded(BaseEntity data, int reqId) {

            }
        });
    }
    /**
     * 通过经纬度逆编码获取城市
     *
     * @param latLonPoint 经纬度位置的实体
     */
    private void getAddress(LatLonPoint latLonPoint) {
        RegeocodeQuery query = new RegeocodeQuery(latLonPoint, 200,
                GeocodeSearch.AMAP);// 第一个参数表示一个Latlng，第二参数表示范围多少米，
        // 第三个参数表示是火系坐标系还是GPS原生坐标系
        mGeocodeSearch.getFromLocationAsyn(query);// 设置异步逆地理编码请求
    }

    /**
     * 高德逆地理编码回调方法
     */
    @Override
    public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int i) {
        if (i == AMapException.CODE_AMAP_SUCCESS) {
            if (regeocodeResult != null && regeocodeResult.getRegeocodeAddress() != null
                    && regeocodeResult.getRegeocodeAddress().getFormatAddress() != null) {
                String current = regeocodeResult.getRegeocodeAddress().getCity();
                regeocodeResult.getRegeocodeAddress().toString();
                mView.RefreshPointCity(current);
                L.d("------------------定位到的城市:" + regeocodeResult.getRegeocodeAddress().getDistrict());
                L.d("------------------定位到的城市:" + regeocodeResult.getRegeocodeAddress().getFormatAddress());
                L.d("------------------定位到的城市:" + regeocodeResult.getRegeocodeAddress().getProvince());
                L.d("------------------getStreetNumber定位到的城市:" + regeocodeResult.getRegeocodeAddress().getDistrict());
                L.d("------------------getStreetNumber定位到的城市:" + regeocodeResult.getRegeocodeAddress().getNeighborhood());
                L.d("------------------getStreetNumber定位到的城市:" + regeocodeResult.getRegeocodeAddress().getRoads());
                L.d("------------------getBusinessAreas定位到的城市:" + regeocodeResult.getRegeocodeAddress().getBusinessAreas());
                L.d("------------------getStreetNumber定位到的城市:" + regeocodeResult.getRegeocodeAddress().getStreetNumber());
            } else {
                //没有搜索到相关数据！
            }
        } else {
            //逆编码失败
        }
    }

    /**
     * 高德地理编码回调方法
     *
     * @param geocodeResult 位置信息
     * @param i             响应码：1000为成功，其他为失败
     */
    @Override
    public void onGeocodeSearched(GeocodeResult geocodeResult, int i) {
        if (mView == null)
            return;

        if (i == 1000) {
            if (geocodeResult != null && geocodeResult.getGeocodeAddressList() != null &&
                    geocodeResult.getGeocodeAddressList().size() > 0) {
                GeocodeAddress geocodeAddress = geocodeResult.getGeocodeAddressList().get(0);
                double latitude = geocodeAddress.getLatLonPoint().getLatitude();//纬度
                double longititude = geocodeAddress.getLatLonPoint().getLongitude();//经度
//                String adcode = geocodeAddress.getAdcode();//区域编码
                //使地区显示指定的区域
                String city = geocodeAddress.getCity();
                mView.RefreshPointCity(city);
                mView.RefreshMapCamera(latitude, longititude);
            } else {
//                btn_search_left.setText(mCurrentCity);
                mView.showError("城市定位出错");
                mView.RefreshPointCity(mOldCity);
            }
        } else {
            mView.showError("城市定位出错");
            mView.RefreshPointCity(mOldCity);
        }
    }

    /**
     * 手动定位回调
     *
     * @param aMapLocation
     */
    @Override
    public void onLocationChanged(AMapLocation aMapLocation) {

        if (mView == null)
            return;

        if (aMapLocation.getErrorCode() == AMapLocation.LOCATION_SUCCESS) {
            //地理逆编码
            L.d("------------------onLocationChanged:" + aMapLocation.getAddress());
            LatLonPoint lonPoint = new LatLonPoint(aMapLocation.getLatitude(), aMapLocation.getLongitude());
            getAddress(lonPoint);
            //获取定位成功，进行打开
            double[] doubles = GPSUtils.gcj02_To_Bd09(aMapLocation.getLatitude(), aMapLocation.getLongitude());
            UpClockInInfo(doubles[0], doubles[1]);
        } else {
            //定位失败
            ToastUtil.showToastLong(Factory.app(), "打卡失败，请重新再试");
        }
    }

    private void UpClockInInfo(double latitude, double longitude) {
        if (!(latitude == 0 && longitude == 0)) {
            NetHelper.UserClockIn(latitude, longitude, this);
        }
    }

}
